home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
netconf
/
process.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-28
|
6KB
|
281 lines
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <linux/param.h>
#include <limits.h>
#include <time.h>
#include "netconf.h"
#include "../xconf/xconf.h"
#include "netconf.m"
/*
Read the first line of a file
Return -1 if any error.
*/
static int process_readfile (const char *path, char *buf, int sizebuf)
{
int ret = -1;
// No error message signaled as "path" is a file under /proc/pid
// and the process may vanish while we are reading it.
FILE *fin = fopen (path,"r");
if (fin != NULL){
if (fgets (buf,sizebuf-1,fin)!=NULL){
ret = 0;
}
fclose (fin);
}
return ret;
}
struct PS_PROC {
char cmdline[256], user[10], cmd[40], state, ttyc[4];
int uid, pid, ppid, pgrp, session, tty, tpgid, utime, stime,
cutime, cstime, counter, priority, start_time, signal, blocked,
sigignore, sigcatch;
unsigned int flags, min_flt, cmin_flt, maj_flt, cmaj_flt, timeout,
it_real_value, vsize, rss, rss_rlim, start_code, end_code,
start_stack, kstk_esp, kstk_eip, wchan;
};
/*
Read the file /proc/pid/stat into the struct PS_PROC
Return -1 if any error.
*/
static int process_readstat(int pid, PS_PROC &_psp)
{
int ret = -1;
char tmppath[PATH_MAX];
sprintf (tmppath,"/proc/%d/stat",pid);
char buf[PATH_MAX];
if (process_readfile (tmppath,buf,sizeof(buf))!=-1){
PS_PROC psp;
sscanf(buf, "%d %s %c %d %d %d %d %d %u %u "
"%u %u %u %d %d %d %d %d %d %u "
"%u %d %u %u %u %u %u %u %u %u %u "
"%u %u %u %u\n",
&psp.pid, psp.cmd, &psp.state, &psp.ppid,
&psp.pgrp, &psp.session, &psp.tty, &psp.tpgid,
&psp.flags, &psp.min_flt, &psp.cmin_flt,
&psp.maj_flt, &psp.cmaj_flt,
&psp.utime, &psp.stime, &psp.cutime, &psp.cstime,
&psp.counter, &psp.priority, &psp.timeout,
&psp.it_real_value, &psp.start_time,
&psp.vsize, &psp.rss, &psp.rss_rlim,
&psp.start_code, &psp.end_code, &psp.start_stack,
&psp.kstk_esp, &psp.kstk_eip,
&psp.signal, &psp.blocked, &psp.sigignore, &psp.sigcatch,
&psp.wchan);
_psp = psp;
ret = 0;
}
return ret;
}
/*
Information about a process ID
*/
PUBLIC PROC::PROC (int _pid, PROC *_next)
{
next = _next;
pid = _pid;
path = NULL;
name = NULL;
char tmppath[PATH_MAX];
sprintf (tmppath,"/proc/%d/cmdline",_pid);
char buf[PATH_MAX];
PS_PROC psp;
if (process_readfile (tmppath,buf,sizeof(buf))!=-1){
if (sscanf (buf,"%s",tmppath)==1){
// Small patch for sendmail
char *pt = strchr(tmppath,':');
if (pt != NULL) *pt = '\0';
path = strdup(tmppath);
}
}else if (process_readstat(_pid,psp)!=-1){
strcpy (buf,psp.cmd[0] == '(' ? psp.cmd+1 : psp.cmd);
char *pt = strchr(buf,')');
if (pt != NULL) *pt = '\0';
path = strdup(buf);
}
if (path != NULL){
name = strrchr(path,'/');
if (name != NULL){
name++;
}else{
name = path;
}
}
}
PUBLIC PROC::~PROC ()
{
free (path);
}
/*
Return the next PROC in the list or NULL.
*/
PUBLIC PROC *PROC::getnext ()
{
return next;
}
/*
Return != 0 if the information on the process was read properly.
*/
PUBLIC int PROC::isok ()
{
return path != NULL;
}
/*
Return the path (command line) of a process
*/
PUBLIC const char *PROC::getpath ()
{
return path;
}
/*
Return the name (command line) of a process
*/
PUBLIC const char *PROC::getname ()
{
return name;
}
/*
Send a signal to the process.
*/
PUBLIC int PROC::kill (int signo)
{
int ret = 0;
if (!simul_ison()){
ret = ::kill (pid,signo);
}
return ret;
}
/*
Return the start time of a process.
Return -1 is the process is dead.
*/
PUBLIC long PROC::getstarttime ()
{
long ret = -1;
long uptime;
char buf[200];
if (process_readfile ("/proc/uptime",buf,sizeof(buf))!=-1){
uptime = atoi(buf);
PS_PROC psp;
if (process_readstat(pid,psp)!=-1){
long seconds = (((uptime * 100) - psp.start_time) / HZ);
ret = time(NULL) - seconds;
}
}
return ret;
}
static PROC *first = NULL;
/*
Read all the process currently active and store for usage by
other process_function.
The info is kept for all process_find and isalive call. It
is flushed when process_read is called again.
*/
int process_read()
{
while (first != NULL){
PROC *next = first->getnext();
delete first;
first = next;
}
static char *cmd_ls = "/bin/ls /proc/*/cmdline 2>/dev/null";
FILE *fin = popen (cmd_ls,"r");
int nbproc = -1;
if (fin == NULL){
xconf_error (MSG_U(E_CANTEXEC,"Can't execute command %s\n"));
}else{
nbproc = 0;
char buf[PATH_MAX+1];
while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
if (buf[0] == '/'){
int pid = atoi(buf+6);
if (pid != 0){
PROC *prc = new PROC (pid,first);
if (prc->isok()){
first = prc;
nbproc++;
}else{
delete prc;
}
}
}
}
pclose (fin);
}
return nbproc;
}
static PROC *process_find(const char *path, const char *name)
{
PROC *ret = first;
while (ret != NULL){
const char *ppath = ret->getpath();
const char *pname = ret->getname();
if (strcmp(path,ppath)==0
|| strcmp(name,pname)==0){
break;
}else{
ret = ret->getnext();
}
}
return ret;
}
/*
Check if a process is running at least once
Return -1 or the start time of this process.
*/
PROC *process_find (const char *path)
{
/* #Specification: process / lookup / strategy
When looking for a process, we search first for the exact path
(command line). If this fail, then we use the name only without
path. This should be safe enough to prevent mistake.
*/
if (first == NULL) process_read ();
const char *name = strrchr (path,'/');
name = name == NULL ? path : name + 1;
PROC *ret = process_find (path,"");
if (ret == NULL) ret = process_find ("",name);
return ret;
}
/*
Check if a process is running at least once
Return -1 or the start time of this process.
*/
long process_isactive (const char *path)
{
PROC *prc = process_find (path);
long ret = -1;
if (prc != NULL) ret = prc->getstarttime();
return ret;
}
#ifdef TEST
int main (int argc, char *argv[])
{
for (int i=1; i<argc; i++){
long start = process_isactive(argv[i]);
printf ("%s -> ",argv[i]);
if (start == -1){
printf ("nil\n");
}else{
printf ("%ld %s\n",start,ctime(&start));
}
}
return 0;
}
#endif